﻿namespace ORS.OrderRobot
{
    /// <summary>
    /// 基于cron的间隔执行基类(最小单位为分钟)
    /// </summary>
    public abstract class CronWorkerBase : IBackgroundWorker,ICronWorker
    {
        public abstract string Name { get; }
        /// <summary>
        /// 具体的执行逻辑
        /// </summary>
        /// <returns></returns>
        public virtual async Task ExecuteAsync()
        {
            var now = DateTime.Now.China().TimeOfDay;
            var timeRange = await GetTimeRange();

            // 没有设置时间段，默认都执行
            if (timeRange == null || timeRange.Length < 2 || (!timeRange[0].HasValue && !timeRange[1].HasValue))
            {
                await DoWorkAsync();
                return;
            }

            var start = timeRange[0];
            var end = timeRange[1];

            // 只设置了结束时间
            if (!start.HasValue && end.HasValue)
            {
                if (now <= end.Value.ToTimeSpan())
                    await DoWorkAsync();
                return;
            }

            // 只设置了开始时间
            if (start.HasValue && !end.HasValue)
            {
                if (now >= start.Value.ToTimeSpan())
                    await DoWorkAsync();
                return;
            }

            // 两个都设置了
            if (start.HasValue && end.HasValue)
            {
                var startSpan = start.Value.ToTimeSpan();
                var endSpan = end.Value.ToTimeSpan();
                if (endSpan < startSpan)
                {
                    // 跨天
                    if (now >= startSpan || now <= endSpan)
                        await DoWorkAsync();
                }
                else
                {
                    if (now >= startSpan && now <= endSpan)
                        await DoWorkAsync();
                }
            }
        }
        /// <summary>
        /// 时间段，第一个元素为开始时间，第二个为结束时间
        /// </summary>
        protected abstract Task<TimeOnly?[]> GetTimeRange();
        /// <summary>
        /// 具体的任务实现类
        /// </summary>
        /// <returns></returns>
        protected abstract Task DoWorkAsync();
        /// <summary>
        /// cron
        /// </summary>
        /// <returns></returns>
        public abstract Task<string> GetCronExpressionAsync();

        public Task StartAsync(CancellationToken cancellationToken = default) => Task.CompletedTask;
        public Task StopAsync(CancellationToken cancellationToken = default) => Task.CompletedTask;
    }
}

